/*
*
==============================================================================
*  Name        : 
*  Part of     : Omen Game Engine
*  Description : 
*  Version     : 1.0
*
*  Copyright (c) 2013 Lauri Kortevaara.
* 
==============================================================================
*/

#pragma once

#include "OmenConfig.h"
#include "OmenDataTypes.h"

namespace Omen
{
    class OMEN_API Vector3d
    {
    public:
        Vector3d();
        Vector3d( const Omen::Float& x, const Omen::Float& y, const Omen::Float& z );    /// <summary>Constructs a 3d vector by given x,y,z compnents</summary>
        Vector3d( const Vector3d& other );                                            /// <summary>Constructs a 3d vector by copying another vector3d</summary>
        virtual ~Vector3d();

        virtual Omen::Float length() const;                        /// <summary>Returns the length of this vector</summary>
        virtual Omen::Float squaredLength() const;                 /// <summary>Returns the squared length of this vector</summary>

        void        normalize();                                /// <summary>Normalizes this vetor</summary>
        Vector3d    normalized() const;                            /// <summary>Returns a normalized form of this vector</summary>

        virtual void setCoordinates( const Omen::Float& x, const Omen::Float& y, const Omen::Float& z ); /// <summary>Sets the vector's components</summary>

        virtual Vector3d& operator =( const Omen::Vector3d& other );
        virtual bool operator==( const Omen::Vector3d& other )const { return x==other.x && y == other.y && z == other.z; } /// <summary>Returns true if the two vectors are the same</summary>
        virtual bool operator!=( const Omen::Vector3d& other )const { return x!=other.x || y != other.y || z != other.z; } /// <summary>Returns true if the two vectors are not the same</summary>

        virtual float* operator&();                                 /// Get a float pointer to the vector
        virtual Vector3d& operator*=( Omen::Float scalar );      /// <summary>Multiplies the components of this Vector3d by given scalar and returns a reference to this vector</summary>
        virtual Vector3d& operator*=( const Vector3d& other );    /// <summary>Multiplies the components of this vector by corresponding components of given vector and returns a reference to this vector (e.g. dot product)</summary>
        virtual Vector3d& operator+=( const Vector3d& other );   /// <summary>Adds given Vector3d from this vector and returns a reference to this vector<summary>
        virtual Vector3d& operator-=( const Vector3d& other );   /// <summary>Subtracts given Vector3d from this vector and returns a reference to this vector<summary>
        virtual Vector3d& operator/=( Omen::Float scalar );      /// <summary>Divivdes the components of this Vector3d by given scalar and returns a reference to this vector</summary>

        virtual Vector3d operator*( Omen::Float scalar ) const;      /// <summary>Multiplies the components of this Vector3d by given scalar and returns a reference to this vector</summary>
        virtual Vector3d operator*( const Vector3d& other )const;    /// <summary>Multiplies the components of this vector by corresponding components of given vector and returns a reference to this vector (e.g. dot product)</summary>
        virtual Vector3d operator+( const Vector3d& other )const;   /// <summary>Adds given Vector3d from this vector and returns a reference to this vector<summary>
        virtual Vector3d operator-( const Vector3d& other )const;   /// <summary>Subtracts given Vector3d from this vector and returns a reference to this vector<summary>
        virtual Vector3d operator/( Omen::Float scalar )const;      /// <summary>Divivdes the components of this Vector3d by given scalar and returns a reference to this vector</summary>


        Omen::Float& operator[]( unsigned char col );
        const Omen::Float& operator[]( unsigned char col ) const;
    
    public:
        Omen::Float x,y,z;

    public: // Static member functions
        static Vector3d     crossProduct ( const Vector3d& v1, const Vector3d& v2 );                  /// <summary>Returns cross product of given two vectors. i.e. a vector that is perpendicular to given two vectors</summary>
        static Omen::Float  dotProduct ( const Vector3d& v1, const Vector3d& v2 );                    /// <summmry>Returns dot product of given two vectors</summary>
        static Vector3d     orthoNormalize ( const Vector3d& v1, const Vector3d& v2 );                        /// <summary>Retruns a vector that is perpendicular to two given vectors</summary>
        static Vector3d     orthoNormalize ( const Vector3d& v1, const Vector3d& v2, const Vector3d& v3 );    /// <summary>Returns a vector that is perpendicular to all of three given vectros</summary>
        static Vector3d     project( const Vector3d& u, const Vector3d& v );                          /// <summary>Returns vector u projected on v</summary>

    };   

    /// Non Member Vector3d functions
    /*OMEN_API Omen::Vector3d operator*( Omen::Float scalar, const Omen::Vector3d & vector );
    OMEN_API Omen::Vector3d operator*( const Omen::Vector3d & vector, Omen::Float scalar );
    OMEN_API Omen::Vector3d operator*( const Omen::Vector3d & v1, const Omen::Vector3d & v2 );
    OMEN_API Omen::Vector3d operator+( const Omen::Vector3d & v1, const Omen::Vector3d & v2 );
    OMEN_API Omen::Vector3d operator-( const Omen::Vector3d& vector );
    OMEN_API Omen::Vector3d operator/ ( const Omen::Vector3d& vector, Omen::Float scalar );
    
    OMEN_API bool operator!= ( const Omen::Vector3d & v1, const Omen::Vector3d & v2 );
    OMEN_API bool operator== ( const Omen::Vector3d & v1, const Omen::Vector3d & v2 );*/
    OMEN_API const Vector3d operator* ( Omen::Float scalar, const Vector3d& quaternion );
    //OMEN_API const Omen::Vector3d operator+( const Omen::Vector3d& v1,const Omen::Vector3d& v2  );
};

//OMEN_API const Omen::Vector3d operator*( Omen::Float scalar, const Omen::Vector3d& vector );


/// EOF

